﻿# encoding: UTF-8
#
require 'iconv'

# 这个类接收一个map对象作为输入参数
# 对输入参数进行处理，完成初始化工作。
# 类中的每一个public的方法，均对应一个ant target。
# 这个类完成调用ant target，并像target中填充合适的参数。
class PDEHeadlessBuildAutoMate

	#* URL Template : {URL}@{alias}  to avoid name conflict while auto tag
	#* @@KEY_URL_PLUGINS =>"locations of plugins svn",
	#* @@KEY_URL_FEATURES =>"locations of features svn",
	#* @@KEY_URL_ALL =>"locations of svn which contains plugins dir and features dir",
	#* @@KEY_BUILD_FEATURES =>"features to build",
	#* @@KEY_TIMESTAMP =>"timestamp of build, used in buildfeature and tag"
	@@KEY_URL_PLUGINS = "-URL_plugins"
	@@KEY_URL_FEATURES = "-URL_features"
	@@KEY_URL_ALL = "-URL_all"
	@@KEY_BUILD_FEATURES = "-Build_features"
	@@KEY_TIMESTAMP = "-Timestamp"

	@@TEMPLATE_TAG_NAME = "BL_${Timestamp}_${Alias}"
	@@ANT_HELPER_FILE = "ant_helper_file.xml"

	@@ANT_EXECUTE_TEMPLATE = "ant.bat -f #{@@ANT_HELPER_FILE} -listener org.apache.tools.ant.listener.Log4jListener ${Ant_Target} ${Target_Parames} -lib lib/ "

	@@URL_SEPRATE = ["trunk","branches"]

	#初始化参数Map
	#* 以下是必须的参数：
	#* - [-URL_all 或者 -URL_plugins -URL_features] 以上参数二选一，区分的原因是因为给出的SVN地址的目录结构不同,-URL_all 指定的svn地址需要包含plugins以及features两个目录. -URL_plugins以及-URL_features指定的svn地址的目录下，直接为插件工程目录
	#* - [-Build_features] 需要build的feature数组，按照从前到后的顺序进行build
	#* 以下是可选的参数
	#* - [-Timestamp] 将替换build产物的时间戳,如果不指定，默认使用当前系统时间，格式为:yyyyMMddHHmm,e.g. 201201061345
	def initialize(args_map)
		validate_and_init(args_map)
	end

	private

	#根据map初始化参数
	def validate_and_init(map)
		@url_plugin_feature_must = false
		if map[@@KEY_URL_ALL]==nil
		@url_plugin_feature_must = true
		else
		@all_plugins_features = map[@@KEY_URL_ALL]
		@tag_urls = []
		end
		if @url_plugin_feature_must == true
			if map[@@KEY_URL_PLUGINS]==nil or map[@@KEY_URL_FEATURES]==nil
				raise "#{@@KEY_URL_ALL} and #{@@KEY_URL_PLUGINS} #{@@KEY_URL_FEATURES} should exist one"
			end
		@feature_array = map[@@KEY_URL_FEATURES]
		@plugin_array = map[@@KEY_URL_PLUGINS]

		@tag_urls_features = []
		@tag_urls_plugins = []
		end

		if map[@@KEY_TIMESTAMP]!=nil and map[@@KEY_TIMESTAMP][0]!=nil
		@timestamp = map[@@KEY_TIMESTAMP][0]
		else
			@timestamp = get_now_timestamp
		end

		if map[@@KEY_BUILD_FEATURES] != nil and map[@@KEY_BUILD_FEATURES][0] != nil
		@build_features = map[@@KEY_BUILD_FEATURES]
		else
			raise "#{KEY_BUILD_FEATURES} must exist and must specify at least one element"
		end
	end

	#获取当前系统时间戳，格式:'yyyyMMddHHMM'
	#e.g. 201201061301
	def get_now_timestamp
		Time.now.strftime("%Y%m%d%H%M")
	end

	public

	# 自动打tag
	def auto_tag
		ant_target = "tagBranch"
		commands = []

		if @url_plugin_feature_must == true

			@feature_array.each do |item|
				url_and_tag = get_url_and_tag_name(item)
				@tag_urls_features << url_and_tag[1]
				commands << @@ANT_EXECUTE_TEMPLATE.sub(/\${Ant_Target}/,ant_target).sub(/\${Target_Parames}/,"-Dbranch_url=#{url_and_tag[0]} -Dtag_url=#{url_and_tag[1]}")
			end
			@plugin_array.each do |item|
				url_and_tag = get_url_and_tag_name(item)
				@tag_urls_plugins << url_and_tag[1]
				commands << @@ANT_EXECUTE_TEMPLATE.sub(/\${Ant_Target}/,ant_target).sub(/\${Target_Parames}/,"-Dbranch_url=#{url_and_tag[0]} -Dtag_url=#{url_and_tag[1]}")
			end
		else
			@all_plugins_features.each do |item|
				url_and_tag = get_url_and_tag_name(item)
				@tag_urls << url_and_tag[1]
				commands << @@ANT_EXECUTE_TEMPLATE.sub(/\${Ant_Target}/,ant_target).sub(/\${Target_Parames}/,"-Dbranch_url=#{url_and_tag[0]} -Dtag_url=#{url_and_tag[1]}")
			end

		end

		execute_commands(commands)
	end

	# 从自动打的tag中checkout代码
	def checkout_source_code
		if @url_plugin_feature_must == true
			checkout_plugins_features_one_by_one
		else
			checkout_plugins_features_together
		end
	end

	private

	# 从SVN地址中checkout代码
	# 必须指定-URL_features 以及 -URL_plugins
	# - -URL_plugins 以及 -URL_features指向的SVN目录下均为插件工程目录
	def checkout_plugins_features_one_by_one
		ant_target = "cleanCheckout"
		commands = []
		commands << @@ANT_EXECUTE_TEMPLATE.sub(/\${Ant_Target}/,ant_target).sub(/\${Target_Parames}/,"")

		ant_target = "checkoutFromSVN"
		i = 0

		@tag_urls_plugins.each do |item|
			commands << @@ANT_EXECUTE_TEMPLATE.sub(/\${Ant_Target}/,ant_target).sub(/\${Target_Parames}/,"-Dtagurl=#{item} -DdirectoryName=#{i}/plugins")

			i = i + 1
		end
		@tag_urls_features.each do |item|
			commands << @@ANT_EXECUTE_TEMPLATE.sub(/\${Ant_Target}/,ant_target).sub(/\${Target_Parames}/,"-Dtagurl=#{item} -DdirectoryName=#{i}/features")
			i = i + 1
		end
		execute_commands(commands)
	end

	# 根据输入的地址，返回一个包含两个元素的数组，第一个元素返回原url，第二个元素返回tag的地址
	def get_url_and_tag_name(item)
		command = String.new
		url_alias = item.split("@")
		url = url_alias[0]
		tag_alias = url_alias[1]
		tag_name = @@TEMPLATE_TAG_NAME.sub(/\${Timestamp}/,@timestamp).sub(/\${Alias}/,tag_alias)

		seprate_index = nil
		@@URL_SEPRATE.each do |seprate|
			if url.index(seprate) != nil
			seprate_index = url.index(seprate)
			break
			end
		end

		raise "URL must contains one of #{@@URL_SEPRATE} " if seprate_index == nil
		result_tag_url = "#{url[0,seprate_index]}tags/#{tag_name}"

		return [url,result_tag_url]
	end

	# 执行命令列表
	def execute_commands(command_array)
		command_array.each do |command|
			command = Iconv.conv("GBK","UTF-8", command )
			puts command
			system(command)
		end
	end

	# 从SVN地址中checkout代码
	# 必须指定-URL_all
	# -URL_all中指定的svn url目录下，应该包含两个目录：
	# - features
	# - plugins
	def checkout_plugins_features_together
		ant_target = "cleanCheckout"
		commands = []
		commands << @@ANT_EXECUTE_TEMPLATE.sub(/\${Ant_Target}/,ant_target).sub(/\${Target_Parames}/,"")
		ant_target = "checkoutFromSVN"
		for i in (0...@tag_urls.size) do
			commands << @@ANT_EXECUTE_TEMPLATE.sub(/\${Ant_Target}/,ant_target).sub(/\${Target_Parames}/,"-Dtagurl=#{@tag_urls[i]} -DdirectoryName=#{i}")
		end
		execute_commands(commands)
	end

	public

	# 编译所有的feature
	def build_features
		ant_target = "buildFeature"
		remove_file_readonly
		copy_to_buildHome
		commands = []
		@build_features.each do |feature|
			commands << @@ANT_EXECUTE_TEMPLATE.sub(/\${Ant_Target}/,ant_target).sub(/\${Target_Parames}/,"-Dtimestamp=#{@timestamp} -Dbuildfeaturename=#{feature}")
		end
		execute_commands(commands)
	end

	# 将编译产生的文件归档并发布到updatesite上
	def deploy_to_updatesite_and_archive
		ant_target = "copyToUpdateSiteAndArchive"
		command = @@ANT_EXECUTE_TEMPLATE.sub(/\${Ant_Target}/,ant_target).sub(/\${Target_Parames}/,"-Dtimestamp=#{@timestamp}")
		commands = []
		commands << command
		execute_commands(commands)
	end

	# 删除文件的只读属性
	def remove_file_readonly
		ant_target = "removeManifestFileReadOnly"
		command = @@ANT_EXECUTE_TEMPLATE.sub(/\${Ant_Target}/,ant_target).sub(/\${Target_Parames}/,"")
		commands = []
		commands << command
		execute_commands(commands)
	end

	#将checkout下的源码拷贝到buildHome中
	#* 拷贝过程中将过滤到checkout下第一级目录，比如,checkout下的目录结构如下：
	#* - a
	#* - - plugins
	#* - - features
	#* - b
	#* - - plugins
	#* - - features
	#* 将只拷贝plugins与features目录
	def copy_to_buildHome
		ant_target = "copyBuildFiles"
		command = @@ANT_EXECUTE_TEMPLATE.sub(/\${Ant_Target}/,ant_target).sub(/\${Target_Parames}/,"")
		commands = []
		commands << command
		execute_commands(commands)
	end
end

